#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;

// #define ONLINE_JUDGE

#ifndef ONLINE_JUDGE
#define dbg(x...)                             \
	{                                         \
		cerr << "\033[32;1m" << #x << " -> "; \
		err(x);                               \
	}
void err()
{
	cerr << "\033[39;0m" << endl;
}
template <typename T, typename... A>
void err(T a, A... x)
{
	cerr << a << ' ';
	err(x...);
}
#else
#define dbg(...)
#endif

typedef long long LL;

const int N = 2005;

// // typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> T;
// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> T;
// // tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> S;
// T S;

// vector<int> G[N];
// int n;
// int siz[N], p[N], c[N], a[N];
// void dfs1(int u)
// {
// 	siz[u] = 1;
// 	for (int v : G[u])
// 	{
// 		dfs1(v);
// 		siz[u] += siz[v];
// 	}
// }

// int findOrder(const T &t, int val)
// {
// 	auto p = t.find_by_order(val);
// 	if (p == t.end())
// 	{
// 		dbg("findOrder", val);
// 		puts("NO");
// 		exit(0);
// 	}
// 	return *p;
// }

// int orderOfKey(const T &t, int val)
// {
// 	if (t.find(val) == t.end())
// 	{
// 		dbg("orderOfKey", val);
// 		puts("NO");
// 		exit(0);
// 	}
// 	return t.order_of_key(val);
// }

// void dfs2(int u, int st_val)
// {
// 	int now_order = orderOfKey(S, st_val) + c[u];
// 	a[u] = findOrder(S, now_order);
// 	S.erase(a[u]);
// 	if (!G[u].size())
// 		return;
// 	st_val = *S.lower_bound(st_val);
// 	dbg(u, st_val, a[u]);
// 	// for (int v : G[u])
// 	for (int i = 0; i < (int)G[u].size(); ++i)
// 	{
// 		int v = G[u][i];
// 		int newVal = st_val;
// 		int newOrder = orderOfKey(S, st_val) + siz[v];
// 		dbg(newVal, newOrder, st_val);
// 		if (i < G[u].size() - 1)
// 			st_val = findOrder(S, newOrder);
// 		dfs2(v, newVal);
// 	}
// }

// int main(int argc, char const *argv[])
// {
// 	freopen("in.txt", "r", stdin);

// 	scanf("%d", &n);
// 	int root = 0;
// 	for (int i = 1; i <= n; ++i)
// 	{
// 		scanf("%d%d", &p[i], &c[i]);
// 		if (!p[i])
// 			root = i;
// 		else
// 			G[p[i]].push_back(i);
// 	}

// 	dfs1(root);
// 	for (int i = 1; i <= n; ++i)
// 		S.insert(i);

// 	dfs2(root, 1);
// 	puts("YES");
// 	for (int i = 1; i <= n; ++i)
// 		printf("%d%c", a[i], i == n ? '\n' : ' ');
// 	return 0;
// }

vector<int> pool[N];

int n, p[N], c[N], a[N];

int siz[N];

vector<int> G[N];

void dfs1(int u)
{
	siz[u] = 1;
	for (int v : G[u])
	{

		dfs1(v);
		siz[u] += siz[v];
	}
}

void dfs2(int u)
{
	if (c[u] + 1 > siz[u])
	{
		puts("NO");
		exit(0);
	}
	for (int i=0; i<(int)pool[u].size(); ++i)
		dbg(i, pool[u][i]);
	a[u] = pool[u][c[u]];
	
	dbg("dfs2", u, pool[u].size(), c[u], siz[u], a[u]);
	for (int st=0, i=0; i<G[u].size(); ++i)
	{
		int v = G[u][i];
		dbg(st, i, G[u].size(), pool[u].size(), v);
		pool[v].resize(siz[v]);
		for (int j=0, k=st; j<siz[v]; ++k)
		{
			if (pool[u][k] == a[u])
			{
				++st;
				continue;
			}
			pool[v][j++] = pool[u][k];
		}
		dfs2(v);
		st += siz[v];
	}
}

int main(int argc, char const *argv[])
{
	scanf("%d", &n);
	int root = 0;
	for (int i = 1; i <= n; ++i)
	{
		scanf("%d%d", &p[i], &c[i]);
		if (!p[i])
			root = i;
		else
			G[p[i]].push_back(i);
	}

	dfs1(root);

	for (int i=1; i<=n; ++i)
		pool[root].push_back(i);
	dfs2(root);
	puts("YES");
	for (int i=1; i<=n; ++i)
		printf("%d%c", a[i], i==n? '\n':' ');
	return 0;
}
